/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.autoupdate; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.ResourceBundle; import java.util.Date; import java.text.SimpleDateFormat; import java.text.ParsePosition; import org.w3c.dom.*; import org.openide.loaders.XMLDataObject; import org.openide.TopManager; import org.openide.modules.ModuleDescription; import org.openide.util.*; import org.openide.DialogDescriptor; import org.openide.NotifyDescriptor; /** Serves for building an UpdateCache from XML Document * @author Petr Hrebejk */ public class Updates extends Object { /** The ResourceBundle */ private static final ResourceBundle bundle = NbBundle.getBundle( Updates.class ); /** XML Element tag names */ private static final String TAG_MODULE_UPDATES = "module_updates"; // NOI18N private static final String TAG_MODULE = "module"; // NOI18N private static final String TAG_MODULE_GROUP = "module_group"; // NOI18N private static final String TAG_NOTIFICATION = "notification"; // NOI18N private static final String ATTR_NOTIFICATION_URL = "url"; // NOI18N /** The URL of the document */ private URL xmlURL; /** The list of files in case of installing downloaded modules */ private File[] files; /** The XML Document */ private Document document = null; /** List of all modules * @associates ModuleUpdate*/ private ArrayList modules; /** The tree structure of Modules and Groups */ private ModuleGroup rootGroup; /** All installed modules */ static private ModuleDescription[] installedModules; /** Stops checking for new updates */ private boolean checkCanceled; /** The update check progress panel */ ProgressDialog progressDialog; /** Number of modules to check */ private int moduleCount; private boolean pError = false; /** The timeStamp of downloaded xml */ private Date timeStamp = null; /** Text of the notification if any */ private String notificationText = null; /** URL of the notification if any */ private URL notificationURL = null; /** Creates new Updates */ Updates(URL xmlURL) { this.xmlURL = xmlURL; installedModules = Autoupdater.Support.getModuleDescriptions(); } /** Create new Updates for files list - used * for installing downloaded modules */ Updates( File[] files ) { this.files = files; installedModules = Autoupdater.Support.getModuleDescriptions(); } /** Checks for updates in separate thread. Displays progress in a dialog */ void checkUpdates( ProgressDialog progressDialog, final Wizard.Validator validator ) { this.progressDialog = progressDialog; pError = false; checkCanceled = false; Runnable task = new Runnable () { public void run() { parseDocument(); Settings.getShared().setLastCheck( new Date() ); if (!pError && document != null ) buildStructures(); else pError = true; //Settings.getShared().setLastStamp( getTimeStamp() ); validator.setValid( true ); } }; RequestProcessor.postRequest( task ); } /** Builds structures for downloaded modules, the structures are onbly * linear */ void checkDownloadedModules() { modules = new ArrayList(); rootGroup = new ModuleGroup(); for ( int i = 0; i < files.length; i++ ) { ModuleUpdate update = new ModuleUpdate( files[i] ); if ( update.createFromDistribution() ) { if ( update.isUpdateAvailable() ) { modules.add( update ); rootGroup.addItem( update ); } } } } /** Calls static parsing method in XMLDataObject to parse the * document */ private void parseDocument() { if ( checkCanceled ) return; try { document = XMLDataObject.parse( xmlURL, new ErrorCatcher() ); } catch ( org.xml.sax.SAXException e ) { if (Boolean.getBoolean ("netbeans.debug.exceptions")) { // NOI18N System.out.println("URL : " + xmlURL ); // NOI18N e.printStackTrace (); } pError = true; //TopManager.getDefault().notifyException( e ); } catch ( java.io.IOException e ) { if (Boolean.getBoolean ("netbeans.debug.exceptions")) { // NOI18N System.out.println("URL : " + xmlURL ); // NOI18N e.printStackTrace (); } pError = true; // TopManager.getDefault().notifyException( e ); } } /** Builds the linear and the tree structure of module updates. */ private void buildStructures() { if ( checkCanceled ) return; if ( document.getDocumentElement() == null ) { // System.out.println( "WARNING <MODULE> is not element tag" ); // NOI18N } else { modules = new ArrayList(); rootGroup = new ModuleGroup(); NodeList allModules = document.getElementsByTagName( TAG_MODULE ); moduleCount = allModules.getLength(); progressDialog.setGaugeBounds( ProgressDialog.OVERALL_GAUGE, 0, moduleCount ); progressDialog.setGaugeValue( ProgressDialog.OVERALL_GAUGE, 0 ); progressDialog.setLabelText( ProgressDialog.OVERALL_LABEL, "" ); // NOI18N processElement( document.getDocumentElement(), rootGroup ); // Try to read timestamp Node attr = document.getDocumentElement().getAttributes().getNamedItem( "timestamp" ); // NOI18N if ( attr != null ) { String timeString = attr.getNodeValue(); SimpleDateFormat formatter = new SimpleDateFormat( "ss/mm/HH/dd/MM/yyyy" ); // NOI18N ParsePosition pos = new ParsePosition(0); timeStamp = formatter.parse(timeString, pos); } } } /** Finds module and module_group elements in the node's children and * process them *@param element The DOM Element node to be read. */ private void processElement( Element element, ModuleGroup moduleGroup ) { NodeList nodeList = element.getChildNodes(); for( int i = 0; i < nodeList.getLength(); i++ ) { if ( checkCanceled ) return; Node node = nodeList.item( i ); if ( node.getNodeType() != Node.ELEMENT_NODE ) { continue; } if ( ((Element)node).getTagName().equals( TAG_MODULE ) ) { ModuleUpdate update = new ModuleUpdate( xmlURL, node, document.getDocumentElement() ); if ( update.readModuleUpdate() ) { int currentModule = progressDialog.getGaugeValue( ProgressDialog.OVERALL_GAUGE); progressDialog.setLabelText( ProgressDialog.OVERALL_LABEL, update.getName() + " [" + (currentModule + 1) + "/" + moduleCount + "]" ); // NOI18N progressDialog.setGaugeValue( ProgressDialog.OVERALL_GAUGE, currentModule + 1 ); if ( update.isUpdateAvailable() ) { modules.add( update ); moduleGroup.addItem( update ); } } } else if ( ((Element)node).getTagName().equals( TAG_MODULE_GROUP ) ) { ModuleGroup group = new ModuleGroup( node ); moduleGroup.addItem( group ); processElement( (Element)node, group ); } else if ( ((Element)node).getTagName().equals( TAG_NOTIFICATION ) ) { readNotification( node ); } } } void cancelCheck() { checkCanceled = true; } /** Gets the root of the module/module group tree * @return The group in the root of the tree. */ ModuleGroup getRootGroup() { return rootGroup; } /** Gets the linear structure of all module updates i.e. Collection */ Collection getModules() { return modules; } /** Gets the state of pError the file was not parsed */ boolean isError() { return pError; } /** Gets array of currently installed modules */ static ModuleDescription[] getInstalledModules() { return installedModules; } /** Gets Collection of patches installed in the system */ static ModuleDescription[] getInstalledPatches() { return PatchChecker.getPatches(); } /** Returns the time stamp of the downloaded XML file */ Date getTimeStamp() { return timeStamp; } /** Returns notification text if specified otherwise null */ String getNotificationText() { return notificationText; } /** Returns notification URL if specified otherwise null */ URL getNotificationURL() { return notificationURL; } /** Reads the notification */ private void readNotification( Node node ) { if ( getNotificationText() != null ) { return; } try { Node attr = node.getAttributes().getNamedItem( ATTR_NOTIFICATION_URL ); String textURL = attr == null ? null : attr.getNodeValue(); if ( textURL != null ) notificationURL = new URL( textURL ); } catch ( java.net.MalformedURLException e ) { // TopManager.getDefault().notifyException( e ); // let homepage set to null } StringBuffer sb = new StringBuffer(); NodeList innerList = node.getChildNodes(); for( int i = 0; i < innerList.getLength(); i++ ) { if ( innerList.item( i ).getNodeType() == Node.TEXT_NODE ) { sb.append( innerList.item( i ).getNodeValue() ); } } if ( sb.length() > 0 ) notificationText = sb.toString(); else notificationText = null; } class ErrorCatcher implements org.xml.sax.ErrorHandler { private void message (String level, org.xml.sax.SAXParseException e) { pError = true; } public void error (org.xml.sax.SAXParseException e) { // normally a validity error pError = true; } public void warning (org.xml.sax.SAXParseException e) { //parseFailed = true; } public void fatalError (org.xml.sax.SAXParseException e) { pError = true; } } //end of inner class ErrorPrinter } /* * Log * 17 Gandalf 1.16 2/23/00 Petr Hrebejk Notifications added into * autoupdate * 16 Gandalf 1.15 1/13/00 Petr Hrebejk i18 mk3 * 15 Gandalf 1.14 1/12/00 Petr Hrebejk i18n mk2 * 14 Gandalf 1.13 1/12/00 Petr Hrebejk i18n * 13 Gandalf 1.12 1/10/00 Petr Hrebejk Bug in setting last * stamp fixed * 12 Gandalf 1.11 1/3/00 Petr Hrebejk Various bug fixes - * 5097, 5098, 5110, 5099, 5108 * 11 Gandalf 1.10 12/22/99 Petr Hrebejk Various bugfixes * 10 Gandalf 1.9 12/20/99 Petr Hrebejk Autocheck & security * finished * 9 Gandalf 1.8 12/1/99 Petr Hrebejk Checkin signatures of * NBM files & automatic autoupdate check added * 8 Gandalf 1.7 11/8/99 Petr Hrebejk Install of downloaded * modules added, Licenses in XML * 7 Gandalf 1.6 11/1/99 Petr Hrebejk Remove of * org.netbeans.core.ModuleUpdater fixed * 6 Gandalf 1.5 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 5 Gandalf 1.4 10/11/99 Petr Hrebejk Version before Beta 5 * 4 Gandalf 1.3 10/10/99 Petr Hrebejk AutoUpdate made to * wizard * 3 Gandalf 1.2 10/8/99 Petr Hrebejk Next development version * 2 Gandalf 1.1 10/7/99 Petr Hrebejk Next development version * 1 Gandalf 1.0 10/7/99 Petr Hrebejk * $ */